#include "formvideo.h"
#include "ui_formvideo.h"

#include <QtDebug>
#include <QTextCodec>
#include <QList>

#define APPID   "***"
#define SDKKey  "***"
#define MERR_ASF_BASE_ALREADY_ACTIVATED (0x16002)

MHandle handle;
QList<ASF_FaceFeature> featureList;
QList<QImage *> imageList;
QList<QLabel *> labelList;
struct FaceData{
    IplImage * image;
    ASF_FaceFeature feature;
};

FormVideo::FormVideo(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormVideo)
{
    ui->setupUi(this);

    labelList.append(ui->label1);
    labelList.append(ui->label2);
    labelList.append(ui->label3);
    labelList.append(ui->label4);
    labelList.append(ui->label5);
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
    timer->start(600);

    //读取所有摄像头信息
    QList<QCameraInfo> infos = QCameraInfo::availableCameras();
    foreach(QCameraInfo info, infos){
        qDebug()<<info.description()<<info.deviceName();
        devicedescripList.append(info.description());
        devicenameList.append(info.deviceName());
    }
    int descripIndex = 0;
    myCamera = new QCamera(devicenameList[descripIndex].toUtf8(), this);
    //创建一个获取图片对象
    cp = new QCameraImageCapture(myCamera);
    //抓取图片的信号
    connect(cp, &QCameraImageCapture::imageCaptured,this, &FormVideo::capturePic);

#if 0
    QVideoWidget *w = new QVideoWidget(widgetVideo);
    w->resize(ui->widget->size());
    myCamera->setViewfinder(w);
    w->show();

#else
    vf = new QCameraViewfinder(ui->widgetVideo);
    vf->resize(ui->widgetVideo->size());
    myCamera->setViewfinder(vf);
    vf->show();

#endif
    myCamera->start();

    setMouseTracking(true);


    /** 1. 激活SDK */
    MRESULT res = ASFActivation(const_cast<char*>(APPID), const_cast<char*>(SDKKey));
    if (MOK == res || MERR_ASF_BASE_ALREADY_ACTIVATED == res)
    {
        qDebug() << "ALActivation sucess: " << res;
    }
    else
    {
        qDebug() << "ALActivation fail: " << res;
    }

    /** 2. 初始化引擎 */
    handle = NULL;
    MInt32 mask = ASF_FACE_DETECT | ASF_FACERECOGNITION | ASF_AGE | ASF_GENDER | ASF_FACE3DANGLE;
    res = ASFInitEngine(static_cast<MInt32>(ASF_DETECT_MODE_IMAGE), ASF_OP_0_ONLY, 16, 5, mask, &handle);
    if (res == MOK)
    {
        qDebug() << "ALInitEngine sucess: " << res;
    }
    else
    {
        qDebug() << "ALInitEngine fail: " << res;
    }


}

FormVideo::~FormVideo()
{
    myCamera->stop();
    vf->close();
    delete ui;
}
void FormVideo::updateTime(){
    cp->capture();
}
void FormVideo::capturePic(int id, const QImage &preview)
{
    searchFaces(QImageToIplImage(preview));

}
IplImage *FormVideo::QImageToIplImage(const QImage & qImage)
{
    int width = qImage.width();
    int height = qImage.height();
    CvSize Size;
    Size.height = height;
    Size.width = width;
    IplImage *IplImageBuffer = cvCreateImage(Size, IPL_DEPTH_8U, 3);
    for (int y = 0; y < height; ++y)
    {
        for (int x = 0; x < width; ++x)
        {
            QRgb rgb = qImage.pixel(x, y);
            CV_IMAGE_ELEM( IplImageBuffer, uchar, y, x*3+0 ) = qBlue(rgb);
            CV_IMAGE_ELEM( IplImageBuffer, uchar, y, x*3+1 ) = qGreen(rgb);
            CV_IMAGE_ELEM( IplImageBuffer, uchar, y, x*3+2 ) = qRed(rgb);
        }
    }
    return IplImageBuffer;
}
QImage *FormVideo::IplImageToQImage(IplImage *image){
    QImage *result;
    if (image){
        uchar * qImageBuffer = NULL;
        int width = image->width;
        int widthStep = image->widthStep;
        int height = image->height;
        QImage::Format format = QImage::Format_Invalid;
        if (IPL_DEPTH_8U == image->depth && 3 == image->nChannels){
            qImageBuffer = (uchar *) malloc(width * height * 4 * sizeof(uchar));
            uchar *QImagePtr = qImageBuffer;
            const uchar *iplImagePtr = (const uchar *) image->imageData;
            format = QImage::Format_RGB32;
            if (!qImageBuffer){
                qDebug() << "Insufficient memory for image buffer!" << endl;
                return result;
            }
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    QImagePtr[0] = iplImagePtr[0];
                    QImagePtr[1] = iplImagePtr[1];
                    QImagePtr[2] = iplImagePtr[2];
                    QImagePtr[3] = 0;

                    QImagePtr += 4;
                    iplImagePtr += 3;
                }
                iplImagePtr += widthStep-3*width;
            }
        } else {
            qDebug("Image format is not supported: depth=%d and %d channels\n", image->depth, image->nChannels);
            return result;
        }
        if (qImageBuffer){
            QImage *result = new QImage(qImageBuffer, image->width, image->height, format);
        }
    } else {
        qDebug() << "Image pointer is NULL" << endl;
    }
    return result;
}

//裁剪图片,做四字节对齐
void FormVideo::CutIplImage(IplImage* src, IplImage* dst, int x, int y)
{
    CvSize size = cvSize(dst->width, dst->height);//区域大小
    cvSetImageROI(src, cvRect(x, y, size.width, size.height));//设置源图像ROI
    cvCopy(src, dst); //复制图像
    cvResetImageROI(src);//源图像用完后，清空ROI
}

void FormVideo::searchFaces(IplImage *img1 ){
    ASF_MultiFaceInfo detectedFaces1 = { 0 };
    ASF_SingleFaceInfo SingleDetectedFaces1 = { 0 };
    ASF_FaceFeature feature1 = { 0 };
    ASF_FaceFeature copyfeature1 = { 0 };
    IplImage* cutImg1 = cvCreateImage(cvSize(img1->width - img1->width % 4, img1->height), IPL_DEPTH_8U, img1->nChannels);
    CutIplImage(img1, cutImg1, 0, 0);


    MRESULT res;
    res = ASFDetectFaces(handle, cutImg1->width, cutImg1->height, ASVL_PAF_RGB24_B8G8R8, (MUInt8*)cutImg1->imageData, &detectedFaces1);

    if (MOK == res)
    {
        SingleDetectedFaces1.faceRect.left = detectedFaces1.faceRect[0].left;
        SingleDetectedFaces1.faceRect.top = detectedFaces1.faceRect[0].top;
        SingleDetectedFaces1.faceRect.right = detectedFaces1.faceRect[0].right;
        SingleDetectedFaces1.faceRect.bottom = detectedFaces1.faceRect[0].bottom;
        SingleDetectedFaces1.faceOrient = detectedFaces1.faceOrient[0];

        res = ASFFaceFeatureExtract(handle, cutImg1->width, cutImg1->height, ASVL_PAF_RGB24_B8G8R8, (MUInt8*)cutImg1->imageData, &SingleDetectedFaces1, &feature1);
        if (res == MOK)
        {
            //取得feature
            copyfeature1.featureSize = feature1.featureSize;
            copyfeature1.feature = (MByte *)malloc(feature1.featureSize);
            memset(copyfeature1.feature, 0, feature1.featureSize);
            memcpy(copyfeature1.feature, feature1.feature, feature1.featureSize);
        }
        else
            qDebug()<<"ASFFaceFeatureExtract 1 fail:"<<res;
    }
    else
        qDebug()<<"ASFDetectFaces 1 fail:"<<res;

    cvReleaseImage(&cutImg1);
    bool isHave=false;
    //
    foreach(ASF_FaceFeature f , featureList )
    {
        // 人脸特征比对
        MFloat confidenceLevel =0;
        res = ASFFaceFeatureCompare(handle, &f, &copyfeature1, &confidenceLevel);
        if (res != MOK){
            qDebug()<<"ASFFaceFeatureCompare fail:"<<res;
            isHave=true;
            break;
        }
        else
            qDebug()<<"confidenceLevel:"<<confidenceLevel;
        if(confidenceLevel > 0.4){
            isHave=true;
            break;
        }
    }
    qDebug()<<"是否存在"<<isHave;
    if (!isHave) {
        int left=SingleDetectedFaces1.faceRect.left;
        int top=SingleDetectedFaces1.faceRect.top;
        int width=SingleDetectedFaces1.faceRect.right-SingleDetectedFaces1.faceRect.left;
        int height=SingleDetectedFaces1.faceRect.bottom-SingleDetectedFaces1.faceRect.top;
        IplImage* cutFace = cvCreateImage(cvSize(width - width % 4, height), IPL_DEPTH_8U, img1->nChannels);
        //忽略边缘头像
        if(left<0 ||top<0){
            cvReleaseImage(&img1);
            cvReleaseImage(&cutFace);
            return;
        }
        CutIplImage(img1, cutFace, left, top);
        featureList.append(copyfeature1);
        QImage * img=IplImageToQImage(cutFace);

        cvReleaseImage(&cutFace);
        imageList.append(img);

        if (featureList.count()>5) {
            featureList.removeFirst();
            imageList.removeFirst();
        }
        show_facePic();
    }
    cvReleaseImage(&img1);

}
void FormVideo::show_facePic(){
    for (int i = 0; i < labelList.count(); i++)
    {
        labelList[i]->setPixmap(QPixmap(""));
    }

    for (int i = 0; i < imageList.count(); i++)
    {
        QPixmap pix = QPixmap::fromImage(*imageList[i]);
        if (pix.isNull()) {
            continue;
        }
        pix = pix.scaled(labelList[i]->size(), Qt::KeepAspectRatio);
        labelList[i]->setPixmap(pix);

    }

}

void FormVideo::on_pushButton_clicked()
{
    emit switchF();
    //    QNetworkRequest request;
    //    QNetworkAccessManager* naManager = new QNetworkAccessManager(this);
    //    QMetaObject::Connection connRet = QObject::connect(naManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
    //    Q_ASSERT(connRet);
    //    request.setUrl(QUrl("http"));
    //    QNetworkReply* reply = naManager->get(request);
    //    qDebug()<<'i';
}

void FormVideo::requestFinished(QNetworkReply* reply) {
    // 获取http状态码
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(statusCode.isValid())
        qDebug() << "status code=" << statusCode.toInt();

    QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if(reason.isValid())
        qDebug() << "reason=" << reason.toString();

    QNetworkReply::NetworkError err = reply->error();
    if(err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << reply->errorString();
    }
    else {
        // 获取返回内容
        QByteArray ba = reply->readAll();
        QJsonParseError err_rpt;
        QJsonDocument  root_Doc = QJsonDocument::fromJson(ba, &err_rpt);//字符串格式化为JSON
        QJsonObject root_Obj = root_Doc.object();
        QJsonValue data = root_Obj.value("data");
        QString msg=root_Obj.value("msg").toString();
        QString remark = data.toObject().value("remark").toString();

        qDebug()<<msg<<remark;
    }
}







